package com.bnz.config;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bnz.dao.TbSeckillGoodsMapper;
import com.bnz.entity.TbSeckillGoods;
import com.bnz.utils.MyDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * 定时任务配置类
 */
@Configuration // 配置类
@EnableScheduling // 开启定时任务
public class MySchedulingTask {
    // 引入mapper，用于访问数据库
    @Autowired
    private TbSeckillGoodsMapper goodsMapper;
    // 引入redis
    @Autowired
    private StringRedisTemplate redisTemplate;

    // 1、定时加载秒杀商品（隔一段时间进行数据同步）
    @Scheduled(cron = "0/20 * * * * ?") // 每隔20秒进行一次
    public void loadSeckillData(){
        // 1.1、拿到一天12个时间片段（根据当前时间，拿五个）  MyDate:common里的时间工具类
        List<Date> dateMenus = MyDate.getDateMenus();
        // 1.2、遍历时间片段
        for (Date date : dateMenus) {
            // 1.2.1、创建条件构造器
            QueryWrapper<TbSeckillGoods> wrapper = new QueryWrapper<>();
            // 1.2.2、商品秒杀开始时间，要大于现在的时间片段（现在片段14:00 秒杀开始时间要>=14:00）
            wrapper.ge("start_time",date); // start_time:与数据库相应字段一致
            // 1.2.3、秒杀结束时间要小于当前时间片段+2h
            wrapper.lt("end_time",MyDate.addDateHour(date,2));
            // 1.2.4、商品的状态值必须为“1”，1代表该商品被运营商审核通过
            wrapper.eq("status",1);
            // 1.2.5、商品库存量大于0
            wrapper.gt("stock_count",0);
            // 1.2.6、如果数据库中商品id中，redis中不存在，也要添加进redis（新增加的秒杀商品和redis数据同步）
            // opsForValue() 存普通数据类型; boundHashOps:存hash; key:seckillGoods + MyDate.getDateStr(date)
            // MyDate.getDateStr:将时间转换为字符串; date:上面获取到的当前时间片段（两小时为一个）
            Set<Object> keys = redisTemplate.boundHashOps("seckillGoods" + MyDate.getDateStr(date)).keys();
            // 1.2.7、如果这个keys是存在的，就添加进redis
            if (null != keys && keys.size()>0){ // keys.size()>0:有内容
                wrapper.notIn("id",keys); // id不在keys的范围之内
            }
            // 1.2.8、根据上述的条件，进行查询，得到商品列表
            List<TbSeckillGoods> selectList = goodsMapper.selectList(wrapper);

            /**
             * 遍历之后，一个个放redis，有新添加的秒杀商品，直接同步到redis
             * 如果放集合，再放redis，秒杀商品有改变，就得拿出集合来进行改变，修改麻烦；存方便，对于不经常改动，可以使用
             */
            // 1.2.9、将上面的商品放到redis中
            for (TbSeckillGoods goods : selectList) {
                // 1.2.9.1、将商品放进redis
                BoundHashOperations<String, String, String> ops = redisTemplate.boundHashOps("seckillGoods" + MyDate.getDateStr(date));
                // 以ops中的内容为key，goodId为值，转换为字符串
                ops.put(goods.getGoodsId()+"", JSON.toJSONString(goods));
            }

        }
    }
}
